<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns="http://www.w3.org/2000/svg"
	xmlns:svg="http://www.w3.org/2000/svg"
	xmlns:dg="livcos.org/ns/doc/diagram"
	xmlns:xlink="http://www.w3.org/1999/xlink"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:f="livcos.org/ns/xslt/function"
	exclude-result-prefixes="dg f xs svg xlink">

	<xsl:import href="prep.xsl"/>
	<xsl:import href="extend.xsl"/>
	<xsl:import href="connect.xsl"/>
	
	<!-- 
		box or circle refs entity
		path refs entity (relation, inheritance,...)
		connect is a special path with start and end entity ref
		connects are created by the entity relations and could be drawn explicitly
	-->

	<xsl:param name="incl-editor" select="'1'"/>

	<xsl:template match="dg:diagram">
		<xsl:variable name="tmp">
			<xsl:variable name="tmp">
				<xsl:variable name="tmp">
					<!-- render boxes, circles,... -->
					<xsl:apply-templates select="dg:*" mode="prep"/>
				</xsl:variable>
				<!-- measure, resolve and extend -->
				<xsl:apply-templates select="$tmp/*" mode="extend"/>
			</xsl:variable>
			<!-- route the connectors -->
			<xsl:apply-templates select="$tmp/*" mode="connect"/>
		</xsl:variable>
		<!-- render the results -->
		<xsl:apply-templates select="$tmp" mode="render"/>
	</xsl:template>
	
	<xsl:template match="/" mode="render">
		<xsl:variable name="vpMax" select="max(.//@viewPortMaxX), max(.//@viewPortMaxY)"/>
		<xsl:variable name="vpMin" select="min(.//@viewPortMinX), min(.//@viewPortMinY)"/>
		<xsl:variable name="vp" select="f:subV($vpMax, $vpMin)"/>
		<svg version="1.1" width="{$vp[1] + 4}" height="{$vp[2] + 4}">
			<defs>
				<!-- some standard markers -->
				<marker id="bullet" viewBox="0 0 8 8" refX="0" refY="4" markerUnits="strokeWidth"
					markerWidth="4" markerHeight="4" orient="auto">
					<circle cx="4" cy="4" r="4" stroke="none"/>
				</marker>
				<marker id="arrow_start" viewBox="0 0 16 10" refX="0" refY="5" markerUnits="strokeWidth"
					markerWidth="10" markerHeight="8" orient="auto">
					<path d="M 16,0 L 0,5 16,10" fill="none" stroke="black" stroke-width="1"/>
				</marker>
				<marker id="arrow_end" viewBox="0 0 16 10" refX="16" refY="5" markerUnits="strokeWidth"
					markerWidth="10" markerHeight="8" orient="auto">
					<path d="M 0,0 L 16,5 0,10" fill="none" stroke="black" stroke-width="1"/>
				</marker>
				<marker id="arrow_start_fill" viewBox="0 0 16 10" refX="0" refY="5" markerUnits="strokeWidth"
					markerWidth="10" markerHeight="8" orient="auto">
					<path d="M 0,5 L 16,0 16,10 z"/>
				</marker>
				<marker id="arrow_end_fill" viewBox="0 0 16 10" refX="16" refY="5" markerUnits="strokeWidth"
					markerWidth="10" markerHeight="8" orient="auto">
					<path d="M 0,0 L 16,5 0,10 z"/>
				</marker>
			</defs>
			<g style="font-size: 16px;" transform="translate({f:printV(f:subV((2,2), $vpMin))})">
				<xsl:apply-templates select="dg:connect" mode="render"/>
				<xsl:apply-templates select="* except dg:connect" mode="render"/>
			</g>
		</svg>
	</xsl:template>
	
	<xsl:template match="dg:box" mode="render">
		<xsl:variable name="w" select="@width div 2"/>
		<xsl:variable name="h" select="@height div 2"/>
		<xsl:variable name="p" select="f:castV(@pos)"/>
		<g id="{@id}" class="box" fill="#44AAAA">
			<xsl:attribute name="transform">
				<xsl:text>translate(</xsl:text>
				<xsl:value-of select="f:subV($p, ($w, $h))"/>
				<xsl:text>)</xsl:text>
				<xsl:if test="@angle != 0">
					<xsl:text>rotate(</xsl:text>
					<xsl:value-of select="@angle"/>
					<xsl:text> </xsl:text>
					<xsl:value-of select="$w"/>
					<xsl:text> </xsl:text>
					<xsl:value-of select="$h"/>
					<xsl:text>)</xsl:text>
				</xsl:if>
			</xsl:attribute>
			<xsl:choose>
				<xsl:when test="svg:*">
					<xsl:apply-templates select="svg:*" mode="render"/>
				</xsl:when>
				<xsl:otherwise>
					<a xlink:href="{@ref}">
						<rect stroke="black" x="0" y="0" width="{@width}" height="{@height}" rx="4" ry="4"/>
						<text x="{$w}" y="{$h + 6}" fill="white" style="text-anchor: middle">
							<xsl:value-of select="."/>
						</text>
					</a>
				</xsl:otherwise>
			</xsl:choose>
		</g>
	</xsl:template>
	
	<xsl:template match="dg:circle" mode="render">
		<g id="{@id}" class="circle" fill="#44AAAA">
			<xsl:attribute name="transform">
				<xsl:text>translate(</xsl:text>
				<xsl:value-of select="@pos"/>
				<xsl:text>)</xsl:text>
			</xsl:attribute>
			<a xlink:href="{@ref}">
				<circle stroke="black" r="{@r}"/>
				<text x="0" y="6" fill="white" style="text-anchor: middle">
					<xsl:value-of select="."/>
				</text>
			</a>
		</g>
	</xsl:template>
	
	<xsl:template match="dg:connect" mode="render">
		<xsl:variable name="path">
			<xsl:apply-templates select="dg:*" mode="path"/>
		</xsl:variable>
		<g class="path">
			<xsl:sequence select="@id"/>
			<xsl:if test="$incl-editor = '1'">
				<path d="M {@startV}{$path} {@endV}" fill="none" stroke="#FFFFFF" stroke-width="5"/>
			</xsl:if>
			<path d="M {@startV}{$path} {@endV}" fill="none" stroke="#556677" stroke-width="1">
				<xsl:if test="@marker-start">
					<xsl:attribute name="marker-start">url(<xsl:value-of select="@marker-start"/>)</xsl:attribute>
				</xsl:if>
				<xsl:if test="@marker-end">
					<xsl:attribute name="marker-end">url(<xsl:value-of select="@marker-end"/>)</xsl:attribute>
				</xsl:if>
			</path>
			<xsl:apply-templates select="dg:*" mode="render"/>
		</g>
	</xsl:template>
	
	<xsl:template match="dg:text" mode="path">
	</xsl:template>
	
	<xsl:template match="dg:line" mode="path">
		<xsl:if test="@to">
			<xsl:text> L</xsl:text>
			<xsl:value-of select="@to"/>
		</xsl:if>
	</xsl:template>
	
	<xsl:template match="dg:path" mode="render">
		<xsl:apply-templates select="dg:*" mode="#current"/>
	</xsl:template>
	
	<xsl:template match="dg:line" mode="render">
		<xsl:variable name="p" as="xs:double*">
			<xsl:choose>
				<xsl:when test="@to">
					<xsl:copy-of select="f:castV(@to)"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:variable name="ps" select="preceding-sibling::*/@to"/>
					<xsl:variable name="prev" select="f:castV(if ($ps) then $ps[1] else ../@startV)"/>
					<xsl:variable name="fs" select="following-sibling::*/@to"/>
					<xsl:variable name="next" select="f:castV(if ($fs) then $fs[1] else ../@endV)"/>
					<xsl:variable name="diff" select="f:subV($next, $prev)"/>
					<xsl:copy-of select="f:addV($prev, ($diff[1] div 2, $diff[2] div 2))"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="id">
			<xsl:choose>
				<xsl:when test="@id">
					<xsl:value-of select="@id"/>
				</xsl:when>
				<xsl:when test="@tmpl">
					<xsl:value-of select="@tmpl"/>:<xsl:value-of select="@tmpl-args"/>
					<xsl:if test="not(@tmpl-args)"><xsl:value-of select="f:printV($p)"/></xsl:if>
				</xsl:when>
				<xsl:otherwise>
					<xsl:text>/livcos.org/type/template/livcos.org/ns/doc/diagram/line#template_1:</xsl:text>
					<xsl:value-of select="position()"/>:<xsl:value-of select="f:printV($p)"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<circle id="{$id}" class="lineTo" cx="{$p[1]}" cy="{$p[2]}" r="3" fill="none"/>
	</xsl:template>
	
	<xsl:template match="dg:text" mode="render">
		<xsl:variable name="eA" select="@anchor = 'end'"/>
		<xsl:variable name="s" select="f:castV(if ($eA) then ../@endV else ../@startV)"/>
		<xsl:variable name="e" select="f:castV(if ($eA) then ../@startV else ../@endV)"/>
		<xsl:variable name="p" as="xs:double*">
			<xsl:choose>
				<xsl:when test="../dg:line | ../dg:curve">
					<xsl:variable name="ps" select="../*/@to"/>
					<xsl:copy-of select="f:castV(if ($eA) then $ps[last()] else $ps[1])"/>
				</xsl:when>
				<xsl:otherwise>
					<xsl:copy-of select="$e"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="v" select="f:subV($p, $s)"/>
		<xsl:variable name="xy" select="$v[1] >= $v[2]"/>
		<xsl:variable name="yx" select="$v[2] > -$v[1]"/>
		<xsl:variable name="r" select="if (@anchor = 'end') then @side != 'right' else @side = 'right'"/>
		<xsl:variable name="lr" select="($xy and $r) or ($yx and not($r))"/>
		<xsl:variable name="t" select="($xy and not($r)) or (not($yx) and $r)"/>
		<xsl:variable name="anchor">
			<xsl:choose>
				<xsl:when test="@align = 'left'">start</xsl:when>
				<xsl:when test="@align = 'right'">end</xsl:when>
				<xsl:when test="@align = 'center'">middle</xsl:when>
				<xsl:when test="$lr">start</xsl:when>
				<xsl:otherwise>end</xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="y" select="if ($t) then -4 else 10"/>
		<text id="{@id}" x="0" y="{$y}" fill="black" style="text-anchor: {$anchor}; font-size: 10px">
			<xsl:attribute name="transform">
				<xsl:text>translate(</xsl:text>
				<xsl:choose>
					<xsl:when test="not(@pos)">
						<xsl:variable name="p1" select="if ($lr) then 3 else -3"/>
						<xsl:variable name="p2" select="if ($t) then -1 else 1"/>
						<xsl:value-of select="f:printV(f:addV($s, ($p1, $p2)))"/>
					</xsl:when>
					<xsl:otherwise>
						<xsl:variable name="p" select="f:castV(@pos)"/>
						<!-- transform the coordinate system
						<xsl:variable name="p1" select="if ($lr) then $p[1] else -$p[1]"/>
						<xsl:variable name="p2" select="if ($t) then -$p[2] else $p[2]"/>
						<xsl:value-of select="f:printV(f:addV(f:castV(../@start), ($p1, $p2)))"/>
						-->
						<xsl:value-of select="f:printV(f:addV($s, $p))"/>
					</xsl:otherwise>
				</xsl:choose>
				<xsl:text>)</xsl:text>
			</xsl:attribute>
			<xsl:value-of select="."/>
		</text>
	</xsl:template>
	
	<xsl:template match="dg:*" mode="render">
	</xsl:template>
	
	<xsl:template match="@* | svg:*" mode="render">
		<xsl:copy>
			<xsl:apply-templates select="@* | node()" mode="#current"/>
		</xsl:copy>
	</xsl:template>
	
	<xsl:template match="svg:image/@xlink:href" mode="render">
		<xsl:attribute name="xlink:href" namespace="http://www.w3.org/1999/xlink" select="f:caller-uri(.)"/>
	</xsl:template>
	
	<xsl:template match="text()" mode="render">
		<xsl:sequence select="."/>
	</xsl:template>
	
</xsl:stylesheet>